using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace TNI
{
    public class Color : Data
    {
        #region privates

        private System.Drawing.Color color;
        private double niveauDeGrisNaturel;
        private double niveauDeGrisCouleurLineaire;
        private double r, g, b, a;

        #endregion


        #region Constructors

        public Color()
        {

            color = new System.Drawing.Color();
            //niveauDeGrisNaturel = SetNiveauDeGrisNaturel();

        }

        public Color(double r, double g, double b)
        {

            //color = new System.Drawing.Color();

            this.r = r;
            this.g = g;
            this.b = b;
            this.a = 0;
            //niveauDeGrisNaturel = SetNiveauDeGrisNaturel();

        }

        #endregion

        #region Accessors

        public double A
        {
            get { return a; }
            set { a = value; }
        }

        public double R
        {
            get { return r; }
            set { r = value; }
        }

        public double G
        {
            get { return g; }
            set { g = value; }
        }

        public double B
        {
            get { return b; }
            set { b = value; }
        }

        #endregion

        #region Artimetical Operators

        //cR3 cR3::operator + (const cR3 &c) const
        //{
        //  return cR3(r+c.r, g+c.g, b+c.b);
        //}

        private static void adjusteColor(ref double r,ref double g,ref double b)
        {
            //if (r > 255)
            //    r = 255;
            //if (r < 0)
            //    r = 0;
            //if (g > 255)
            //    g = 255;
            //if (g < 0)
            //    g = 0;
            //if (b > 255)
            //    b = 255;
            if (b < 0)
                b = 0;
            if (r > 1)
                r = 1;
            if (r < 0)
                r = 0;
            if (g > 1)
                g = 1;
            if (g < 0)
                g = 0;
            if (b > 1)
                b = 1;
            if (b < 0)
                b = 0;
        }

        public static Color operator +(Color c1, Color c2)
        {
            double r = c1.R + c2.R;
            double g = c1.G + c2.G;
            double b = c1.B + c2.B;

            adjusteColor(ref r, ref g, ref b);

            return new Color(r,g , b);
        }

        //cR3 & cR3::operator += (const cR3 &c)
        //{
        //  r+=c.r; g+=c.g; b+=c.b;
        //  return *this;
        //}


        //cR3 cR3::operator - () const
        //{
        //  return cR3(-r,-g,-b);
        //}


        //cR3 cR3::operator - (const cR3 &c) const
        //{
        //  return cR3(r-c.r, g-c.g, b-c.b);
        //}


        //cR3 & cR3::operator -= (const cR3 &c)
        //{
        //  r-=c.r; g-=c.g; b-=c.b;
        //  return *this;
        //}

        public static Color operator * (Color c,double k)
        {
            double r = c.R * k;
            double g = c.G * k;
            double b = c.B * k;

            adjusteColor(ref r, ref g, ref b);

            return new Color(r, g, b);
            //return new Color(c.R * k, c.G * k, c.B * k);
        }



        public static Color operator *(Color c1, Color c2)
        {
            //double r = (c1.R / 255) * (c2.R / 255);
            //double g = (c1.G / 255) * (c2.G / 255);
            //double b = (c1.B / 255) * (c2.B / 255);
            //r *= 255;
            //g *= 255;
            //b *= 255;

            double r = (c1.R) * (c2.R);
            double g = (c1.G) * (c2.G);
            double b = (c1.B) * (c2.B);
            
            adjusteColor(ref r, ref g, ref b);

            return new Color(r, g, b);
          //return new Color(c1.R*c2.R, c1.G * c2.G, c1.B*c2.B);
        }

        //cR3 & cR3::operator *= (const cR3 &c)
        //{
        //  r*=c.r; g*=c.g; b*=c.b;
        //  return *this;
        //}


        //cR3 cR3::operator / (double k) const
        //{
        //  assert(k > EPS);
        //  return cR3(r/k, g/k, b/k);
        //}


        //cR3 & cR3::operator /= (double k)
        //{
        //  assert(k > EPS);
        //  r/=k; g/=k; b/=k;
        //  return *this;
        //}


        //cR3 cR3::operator / (const cR3 &c) const
        //{
        //  assert(c.r > EPS && c.g > EPS && c.b > EPS);
        //  return cR3(r/c.r, g/c.g, b/c.b);
        //}


        //cR3 & cR3::operator /= (const cR3 &c)
        //{
        //  assert(c.r > EPS && c.g > EPS && c.b > EPS);
        //  r/=c.r; g/=c.g; b/=c.b;
        //  return *this;
        //}


        //bool cR3::operator == (const cR3 &c) const
        //{
        //  return fabs(r-c.r)<=EPS && fabs(g-c.g)<=EPS && fabs(b-c.b)<=EPS;
        //}


        //bool cR3::operator != (const cR3 &c) const
        //{
        //  return !(*this == c);
        //}


        //double cR3::operator [] (unsigned i) const
        //{
        //  assert(i < 3);
        //  return i==0?r:(i==1?g:b);
        //}


        //double & cR3::operator [] (unsigned i)
        //{
        //  assert(i < 3);
        //  return i==0?r:(i==1?g:b);
        //}


        //double cR3::operator ! (void) const
        //{
        //  return SQ(r)+SQ(g)+SQ(b);
        //}


        #endregion



        public System.Drawing.Color RGBColor 
        { 
            get 
            {

                int R = Convert.ToInt32(r * 255);
                int G = Convert.ToInt32(g * 255);
                int B = Convert.ToInt32(b * 255);

                //R *= 255;
                //G *= 255;
                //B *= 255;
                //A *= 255;

                return System.Drawing.Color.FromArgb(R, G, B);
            
            }
            set 
            { 
                color = value;
                r = color.R;
                g = color.G;
                b = color.B;
                a = color.A;

                r /= 255;
                g /= 255;
                b /= 255;
                a /= 255;
                //niveauDeGrisNaturel = SetNiveauDeGrisNaturel();
                //niveauDeGrisCouleurLineaire = SetNiveauDeGrisCouleurLineaire();
            }
        }

        public double NiveauDeGrisNaturel
        {
            get
            {
                niveauDeGrisNaturel = SetNiveauDeGrisNaturel();
                return niveauDeGrisNaturel;
            }
            set
            {
                niveauDeGrisNaturel = value;
                //double niveauDeGris = r * 0.2125 + b * 0.0721 + g * 0.7154;
                this.r = value / 0.2125;
                this.b = value / 0.0721;
                this.g = value / 0.7154;

                //this.r *= 256;
                //this.g *= 256;
                //this.b *= 256;
                

            }

        }


        public double NiveauDeGrisCouleurLineaire
        {
            get
            {
                niveauDeGrisCouleurLineaire = SetNiveauDeGrisCouleurLineaire();
                return niveauDeGrisCouleurLineaire;
                
            }
            set
            {
                niveauDeGrisCouleurLineaire = value;
            }

        }

        private double SetNiveauDeGrisNaturel()
        {

            //byte R = color.R ;
            //byte B = color.B ;
            //byte G = color.G ;

            double niveauDeGris = r* 0.2125 + b * 0.0721 + g * 0.7154;

            return niveauDeGris;

        }

        private double SetNiveauDeGrisCouleurLineaire()
        {

            //byte R = color.R;
            //byte B = color.B;
            //byte G = color.G;

            double niveauDeGris = r * 0.299 * +b * 0.114 * +g * 0.587;

            return niveauDeGris;

        }
            
    }
}
